using System;

namespace NobleTech.Products.CreatureKingdom
{
    public class OrganismStats
    {
        public enum Genders { Male, Female }
        public Genders Gender;
        public float MaleBirths = 0.5f;

        public uint
            // When can start mating
            PubertyAge,
            // When Size reaches its maximum values
            FullyGrownAge,
            // When SightRange, MaxSpeed start to deteriorate
            FrailtyAge,
            // When going to die (nice to know!)
            LifeSpan;
        public uint GestationPeriod;
        public double
            // Size at birth
            BornSize,
            // Fully grown size
            FullyGrownSize;

        // Distance that can see
        public double SightRange;
        // The number of things that can do at once (number of limbs)
        public uint MaxInteractions;
        // The max speed once fully grown
        public double MaxSpeedForwards,
            MaxSpeedBackwards;
        // Maximum amount of energy
        public double Stamina;
        // The amount of CPU that the creature is allowed to use
        public double Intelligence;

        // Amount of damage done when attacking / defending
        public double MaxStrength;
        // Ability to hit a moving target
        public double Coordination;
        // Ability to withstand damage done when attacked
        public double ArmourFront,
            ArmourBack;
        // Ability to dodge attacks
        public double Agility;
        // Distance can reach to attack
        public double AttackRange;

        // How hard it is for other people to see you (especially when not moving) (0 to 1)
        public float Camoflage;

        // Angle that can see
        public double SightFieldOfView = 2.6;

        // The registered name of the author of this creature
        // A creature with parents created by different authors has no creator
        public string Creator;
        // To successfully mate with another creature, they must both be of the same species
        public string Species;
        // A creature with parents of different Subspecies has no Subspecies
        public string Subspecies;
        // The stats of this creature's mother and father
        public OrganismStats Mother, Father;

        private OrganismStats PickAParent()
        {
            return WorldStats.RandomGenerator.Next(2) == 0 ? Mother : Father;
        }
        private OrganismStats SameSexParent
        {
            get
            {
                return this.Gender == Genders.Male ? this.Father : this.Mother;
            }
        }

        public OrganismStats()
        {
        }

        public OrganismStats(WorldStats world, OrganismStats Mother, OrganismStats Father)
        {
            if (Mother.Species != Father.Species)
                throw new ApplicationException("Mother and Father are of different species");
            this.Mother = Mother;
            this.Father = Father;
            if (Mother.Creator == Father.Creator)
                this.Creator = Father.Creator;
            else
                this.Creator = null;
            this.Gender = WorldStats.RandomGenerator.NextDouble() < MaleBirths
                ? Genders.Male : Genders.Female;

            this.PubertyAge = world.Mutate(SameSexParent.PubertyAge);
            this.FullyGrownAge = world.Mutate(SameSexParent.FullyGrownAge);
            this.FrailtyAge = world.Mutate(SameSexParent.FrailtyAge);
            this.LifeSpan = world.Mutate(SameSexParent.LifeSpan);
            this.BornSize = world.Mutate(PickAParent().BornSize);
            this.FullyGrownSize = world.Mutate(PickAParent().FullyGrownSize);
            this.SightRange = world.Mutate(PickAParent().SightRange);
            this.MaxSpeedForwards = world.Mutate(PickAParent().MaxSpeedForwards);
            this.MaxSpeedBackwards = world.Mutate(PickAParent().MaxSpeedBackwards);
            this.SightFieldOfView = world.Mutate(PickAParent().SightFieldOfView);
        }
    }
}
